package gbench.commonApp.data;

import java.lang.reflect.Array;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import gbench.common.fs.XlsFile.DataMatrix;
import gbench.common.fs.XlsFile.TypeU;

import static gbench.common.tree.LittleTree.IRecord.*;
import static gbench.common.tree.LittleTree.*;

/**
 * DataMatrix 的应用实例
 * 
 * @author gbench
 *
 */
public class DataMatrixApp {
    /**
     * 
     * @param <T>    矩阵元素的类型
     * @param stream 源数据流程
     * @param tclass 矩阵元素的类型的class
     * @return DataMatrix &lt; T &gt;
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> matrix(final Stream<IRecord> stream, final Class<T> tclass) {
        final Function<IRecord, LinkedHashMap<String, T>> final_row_mapper = e -> {
            final Class<T> final_tclass = tclass == null ? (Class<T>) Object.class : tclass;
            var mm = e.toLhm(final_tclass);
            if (tclass == Object.class) {
                var new_mm = new LinkedHashMap<String, Object>(mm);
                mm = (LinkedHashMap<String, T>) new_mm;
            } // if
            return mm;
        };
        return DataMatrix.of(stream, final_row_mapper, tclass);
    }

    /**
     * 生成一个 DataMatrix 
     * @param stream 源数据的行流，每个元素代表一行数据。
     * @return DataMatrix &lt; T &gt;
     */
    public static DataMatrix<Object> matrix(final Stream<IRecord> stream) {
        return DataMatrix.of(stream, IRecord::toLhm);
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param tclass 矩阵的元素的类型 类型
     * @param recs 行数据列表
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> DMX(final Class<T> tclass, final Stream<IRecord> recs){
        return recs.collect(tmc(tclass));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param recs 行数据列表
     * @param tclass 矩阵的元素的类型 类型
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> DMX( final Class<T>tclass, final IRecord...recs){
        return Stream.of(recs).collect(tmc(tclass));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * 
     * @param tclass 矩阵的元素的类型 类型
     * @param line 数据的行表示：比如 1,2;3,4 表示<br>
     * 1 2 <br>
     * 3 4 <br>
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> DMX( final Class<T> tclass, final String line){
        final var recs = Stream.of(line.split("[\n;]+")).map(IRecord::STRING2REC);
        return recs.collect(tmc(tclass));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param rows 行数据列表
     * @return DataMatrix &lt; Double &gt;
     */
    public static DataMatrix<Double> DBLMX( final IRecord...rows){
        return Stream.of(rows).collect(tmc(Double.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param stream 行数据列表,每个 流元素都代表一行数据。
     * @return DataMatrix &lt; Double &gt;
     */
    public static DataMatrix<Double> DBLMX( final Stream<IRecord> stream){
        return stream.collect(tmc(Double.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param rows 行数据列表
     * @return DataMatrix &lt; Object &gt;
     */
    public static DataMatrix<Object> OBJMX( final IRecord...rows){
        return Stream.of(rows).collect(tmc(Object.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param stream 行数据列表
     * @return DataMatrix &lt; Object &gt;
     */
    public static DataMatrix<Object> OBJMX( final Stream<IRecord> stream){
        return stream.collect(tmc(Object.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param rows 行数据列表
     * @return DataMatrix &lt; T &gt;
     */
    public static DataMatrix<String> STRMX( final IRecord...rows){
        return Stream.of(rows).collect(tmc(String.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param stream 行数据列表
     * @return DataMatrix &lt; T &gt;
     */
    public static DataMatrix<String> STRMX( final Stream<IRecord> stream){
        return stream.collect(tmc(String.class));
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param rows 行数据列表
     * @return DataMatrix &lt; Integer &gt;
     */
    public static DataMatrix<Integer> INTMX( final IRecord...rows){
        return Stream.of(rows).collect(tmc(Integer.class));
    }

    /**
     * 把stream 转换成 数据矩阵
     * @param stream 行数据的元素流
     * @return DataMatrix &lt; T &gt;
     */
    public static DataMatrix<Integer> INTMX( final Stream<IRecord> stream){
        return stream.collect(tmc(Integer.class));
    }
    
    /**
     * 把recs 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param tclass 矩阵的元素的类型 类型
     * @param dfm dframe 结构的IRecord 即  rec的每个元素都表示一个属性维度：列向量。
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> REC2DMX(final Class<T> tclass, final IRecord dfm){
        @SuppressWarnings("unchecked")
        final var final_tclass = tclass == null ? (Class<T>)Object.class:tclass;
        return DataMatrix.of(dfm.toArray2(final_tclass),dfm.keys());
    }
    
    /**
     * 把recs 转换成 数据矩阵 DataMatrix &lt; Object &gt;
     * @param rec dframe 结构的IRecord 即  rec的每个元素都表示一个属性维度：列向量。
     * @return DataMatrix &lt; Object &gt;
     */
    public static DataMatrix<Object> REC2DMX(final IRecord rec){
        return REC2DMX(null,rec);
    }

    /**
     * 把recs转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param recs 列数据列表
     * @param tclass 矩阵的元素的类型 类型
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> DMX2( final Class<T> tclass, final Stream<IRecord> recs){
        return recs.collect(tmc(tclass)).transpose();
    }

    /**
     * 把ccc 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param ccc 行数据列表
     * @param tclass 矩阵的元素的类型 类型
     * @return DataMatrix &lt; T &gt;
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> DMX2(final Class<T> tclass, final Object ...ccc){
        IRecord mm = REC(ccc);
        return DMX(tclass,(Stream<IRecord>)(Object)mm.values().stream()).transpose(mm.keys());
    }

    /**
     * 把ccc 转换成 数据矩阵：构建一个列矩阵
     * @param ccc name0,colum1,name1,colum1, ..., 名称与列向量对应的数据矩阵。
     * @return DataMatrix&lt;Double&gt;
     */
    public static DataMatrix<Object> OBJMX2( final Object ...ccc){
        return DMX2(Object.class,ccc);
    }

    /**
     * 把ccc 转换成 数据矩阵：构建一个列矩阵
     * @param ccc name0,colum1,name1,colum1, ..., 名称与列向量对应的数据矩阵。
     * @return DataMatrix&lt;Double&gt;
     */
    public static DataMatrix<Double> DBLMX2(final Object ...ccc){
        return DMX2(Double.class,ccc);
    }

    /**
     * 把ccc 转换成 数据矩阵：构建一个列矩阵
     * @param ccc name0,colum1,name1,colum1, ..., 名称与列向量对应的数据矩阵。
     * @return DataMatrix&lt;Double&gt;
     */
    public static DataMatrix<Integer> INTMX2( final Object ...ccc){
        return DMX2(Integer.class,ccc);
    }

    /**
     * 把ccc 转换成 数据矩阵：构建一个列矩阵
     * @param ccc name0,colum1,name1,colum1, ..., 名称与列向量对应的数据矩阵。
     * @return DataMatrix&lt;Double&gt;
     */
    public static DataMatrix<Long> LNGMX2( final Object ...ccc){
        return DMX2(Long.class,ccc);
    }

    /**
     * 把ccc 转换成 数据矩阵：构建一个列矩阵
     * @param ccc name0,colum1,name1,colum1, ..., 名称与列向量对应的数据矩阵。
     * @return DataMatrix&lt;Double&gt;
     */
    public static DataMatrix<String> STRMX2( final Object ...ccc){
        return DMX2(String.class,ccc);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param <T> 矩阵元素的类型
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @param tclass 矩阵元素的类型的class
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;T&gt;&gt;
     */
    public static <T> Collector<IRecord, List<IRecord>, DataMatrix<T>> mxclc( final Function<IRecord, IRecord> row_mapper,
            final Class<T> tclass) {

       return mxclc(row_mapper,tclass,null);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param <T> 矩阵元素的类型
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @param tclass 矩阵元素的类型的class
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;T&gt;&gt;
     */
    public static <T> Collector<IRecord, List<IRecord>, DataMatrix<T>> mxclc( final Function<IRecord, IRecord> row_mapper,
            final Class<T> tclass,final List<String> headers) {

        final Supplier<List<IRecord>> supplier = LinkedList::new;
        final BiConsumer<List<IRecord>, IRecord> accumulator = (aa, a) -> aa.add(row_mapper==null?a:row_mapper.apply(a));
        final BinaryOperator<List<IRecord>> combiner = (aa, bb) -> {
            aa.addAll(bb);
            return aa;
        };
        final Function<List<IRecord>, DataMatrix<T>> finisher = ll -> {
            final var mx = matrix(ll.stream(), tclass);
            if(headers!=null)mx.setHeader(headers);
            return mx;
        };

        return Collector.of(supplier, accumulator, combiner, finisher);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Double&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Double>> dblmxclc(
            final Function<IRecord, IRecord> row_mapper) {
        return dblmxclc(row_mapper,null);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Double&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Double>> dblmxclc(
            final Function<IRecord, IRecord> row_mapper, final List<String> headers) {

        return mxclc(row_mapper,Double.class,headers);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *  变换成中间的T为值类型IRecord的流对象。
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Integer &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Integer>> intmxclc(
            final Function<IRecord, IRecord> row_mapper,final List<String> headers) {

       return mxclc(row_mapper,Integer.class,headers);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Integer &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Integer>> intmxclc(
            final Function<IRecord, IRecord> row_mapper) {

        return mxclc(row_mapper,Integer.class,null);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Long &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Long>> lngmxclc( final Function<IRecord, IRecord> row_mapper,final List<String> headers) {

        return mxclc(row_mapper,Long.class,headers);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     * 变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Long &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Long>> lngmxclc( final Function<IRecord, IRecord> row_mapper) {

        return mxclc(row_mapper,Long.class,null);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector &lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Object&gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> objmxclc(
            final Function<IRecord, IRecord> row_mapper) {
    
        return mxclc(row_mapper,Object.class,null);
    }
    
    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector &lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Object&gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> objmxclc(
            final Function<IRecord, IRecord> row_mapper,final List<String> headers) {
    
        return mxclc(row_mapper,Object.class,headers);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;String &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<String>> strmxclc(
            final Function<IRecord, IRecord> row_mapper) {
    
        return mxclc(row_mapper,String.class,null);
    }
    
   /**
    * 一个IRecord的Collector
    * 
    * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
    *                   变换成中间的T为值类型IRecord的流对象。
    * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;String &gt;&gt;
    */
   public static Collector<IRecord, List<IRecord>, DataMatrix<String>> strmxclc(
           final Function<IRecord, IRecord> row_mapper,final List<String> headers) {
   
       return mxclc(row_mapper,String.class,headers);
   }

    /**
     * 一个IRecord的Collector
     * 
     * @return Collector &lt;IRecord,&lt;IRecord&gt;,DataMatrix&lt;Object&gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> objmxclc() {
    
        return objmxclc(null);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param <T> 元素类型
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector &lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Object&gt;&gt;
     */
    public static <T> Collector<IRecord, List<IRecord>, DataMatrix<T>> tmxclc(
            final Function<IRecord, IRecord> row_mapper, final Class<T>tclass) {
    
        final Function<IRecord, IRecord> final_row_mapper = row_mapper == null ? e -> e : row_mapper;
        final Supplier<List<IRecord>> supplier = LinkedList::new;
        final BiConsumer<List<IRecord>, IRecord> accumulator = (aa, a) -> aa.add(final_row_mapper.apply(a));
        final BinaryOperator<List<IRecord>> combiner = (aa, bb) -> {
            aa.addAll(bb);
            return aa;
        };
        final Function<List<IRecord>, DataMatrix<T>> finisher = ll -> matrix(ll.stream(), tclass);
    
        return Collector.of(supplier, accumulator, combiner, finisher);
    }

    /**
     * 一个IRecord的Collector:dblmxclc 的别名
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,IRecord,DataMatrix&lt;Double&gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Double>> DMC( final Function<IRecord, IRecord> row_mapper) {
        return dblmxclc(row_mapper);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,IRecord,DataMatrix&lt;Integer &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Integer>> IMC(
            Function<IRecord, IRecord> row_mapper) {
        return intmxclc(row_mapper);
    }

    /**
     * 一个IRecord的Collector
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Long &gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Long>> LMC( final Function<IRecord, IRecord> row_mapper) {
        
        return lngmxclc(row_mapper);
    }

    /**
     * 一个IRecord的Collector
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,IRecord,DataMatrix&lt;String&gt;&gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<String>> SMC(
            Function<IRecord, IRecord> row_mapper) {
        return strmxclc(row_mapper);
    }

    /**
     * 一个IRecord的Collector
     * @param <T> 元素类型
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @param tclass 元素类型类
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;T &gt;&gt;
     */
    public static <T> Collector<IRecord, List<IRecord>, DataMatrix<T>> TMC(
            final Function<IRecord, IRecord> row_mapper,Class<T>tclass){
        return tmxclc(row_mapper,tclass);
    }

    /**
     * 一个IRecord的Collector:objmxclc 的别名
     * 
     * @param row_mapper 行变换器，把记录的值装换成统一的数据类型 以方便作为数组进行存储:对源数据流
     *                   变换成中间的T为值类型IRecord的流对象。
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Object &gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> OMC(
            final Function<IRecord, IRecord> row_mapper) {
        return objmxclc(row_mapper);
    }

    /**
     * 一个IRecord的Collector:OMC
     * 
     * @return Collector&lt;IRecord,List&lt;IRecord&gt;,DataMatrix&lt;Object &gt;
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> OMC() {

        return objmxclc(null);
    }
    
    /**
     * 生成全 T 类型的向量
     * @param <T> 元素类型
     * @param n 向量的长度
     * @return DataMatri <T>
     */
    public static <T extends Number> DataMatrix<T> vones( final T n){
        @SuppressWarnings("unchecked")
        final T one = P(1).toTarget(n!=null?(Class<T>)n.getClass():(Class<T>)(Object)Object.class);
        return VT(RPTA(n.intValue(),one));
    }
    
    /**
     * 生成全 T 类型的向量 :全 one 的向量
     * @param <T> 元素类型
     * @param n 向量的长度
     * @param one 向量元素：one元 ，什么代表1
     * @return DataMatri <T>
     */
    public static <T> DataMatrix<T> vones( final int n, final T one){
        return VT(RPTA(n,one));
    }
    
    /**
     * 生成全 T 类型的向量 :全 one 的行向量
     * @param <T> 元素类型
     * @param n 向量的长度
     * @param one 向量元素：one元 ，什么代表1
     * @return DataMatri <T>
     */
    public static <T> DataMatrix<T> hones( final int n, final T one){
        return VT(RPTA(n,one)).tp();
    }
    
    /**
     * 生成全 T 类型的向量:行向量
     * @param <T> 元素类型
     * @param n 向量的长度: one元默认为1
     * @return DataMatri <T>
     */
    public static <T extends Number> DataMatrix<T> hones( final T n){
        return vones(n).tp();
    }
    
    /**
     * 生成一个T类型的向量:VT 向量的别名
     * @param <T> 元素类型
     * @param oo 元素数据
     * @return DataMatrix &lt; T &gt;
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> V( final T ...oo){
        return VT(oo);
    }
    
    /**
     * 把一个矩阵按照列 顺序拼接成一个列向量
     * 生成一个T类型的向量:VT 向量的别名
     * @param <T> 元素类型
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> V( final DataMatrix<T> mm){
        return VT(mm.flc2());
    }
    
    /**
     * 把一个矩阵按照行 顺序拼接成一个列向量
     * 生成一个T类型的向量:VT 向量的别名
     * @param <T> 元素类型
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> V2( final DataMatrix<T> mm){
        return VT(mm.flc());
    }

    /**
     * 生成一个学姐级数向量
     * @param <T> 元素的类型
     * @param size 向量长度
     * @param fx : 向量元素生成函数,x->u,x 从0开始知道 n-1
     * @return DataMatrix &lt; T &gt; 一维列向量
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> V( final Number size, final Function<Integer,T> fx){
        final var uu = NATS(size.intValue()).map(Long::intValue).map(fx).collect(Collectors.toList());
        final var uclass = uu.stream().filter(Objects::nonNull)
            .map(e->(Class<T>)e.getClass()).findAny().orElse((Class<T>)Object.class);
        return VT(uu.toArray(n->(T[])Array.newInstance(uclass,n)));
    }

    /**
     * 生成一个T类型的向量
     * @param <T> 元素类型
     * @param oo 元素数据
     * @return DataMatrix &lt; T &gt;
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> VT( final T ...oo){
        final Class<T> clazz = Arrays.stream(oo).filter(e->e!=null)
            .map(e->(Class<T>)e.getClass()).findAny().get();
        final var rec = IRecord.A2REC(oo);
        return DMX(clazz,Stream.of(rec)).transpose();
    }

    /**
     * 把recs 转换成 数据矩阵
     * @param <T> 矩阵的元素的类型
     * @param tclass 矩阵的元素的类型 类型
     * @param line 数据的行表示：比如 1,2;3,4 表示<br>
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; T &gt;
     */
    public static <T> DataMatrix<T> VEC( final Class<T> tclass, final String line){
        final var recs = Stream.of(line.split("[\n;]+")).map(IRecord::STRING2REC);
        return recs.collect(tmc(tclass)).transpose();
    }

    /**
     * double 向量
     * 把recs 转换成 数据矩阵
     * @param oo 列向量数据
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; Double &gt;
     */
    public static <T> DataMatrix<Double> dblvec( final Number ...oo){
        final var rec = IRecord.A2REC(Stream.of(oo).map(Number::doubleValue).toArray());
        return DMX(Double.class,Stream.of(rec)).transpose();
    }

    /**
     * double 向量:把一个Record 变成一个向量
     * @param rec 列向量数据
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; Double &gt;
     */
    public static DataMatrix<Double> dblvec( final IRecord rec){
        return DMX(Double.class,Stream.of(rec)).transpose();
    }

    /**
     * double 向量
     * 把line 转换成 数据矩阵
     * @param line 数据的行表示：比如 1,2;3,4 表示<br>
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; Double &gt;
     */
    public static DataMatrix<Double> dblvec( final String line){
       return VEC(Double.class,line);
    }

    /**
     * int 向量
     * 把recs 转换成 数据矩阵
     * @param line 数据的行表示：比如 1,2;3,4 表示<br>
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; Integer &gt;
     */
    public static DataMatrix<Integer> intvec( final String line){
        return VEC(Integer.class,line);
    }

    /**
     * long 向量
     * 把line 转换成 数据矩阵
     * @param line 数据的行表示：比如 1,2;3,4 表示<br>
     * 1 2<br>
     * 3 4
     * @return DataMatrix &lt; Long &gt;
     */
    public static DataMatrix<Long> lngvec( final String line){
        return VEC(Long.class,line);
    }

    /**
     * 对角矩阵
     * @param <T> 元素类型
     * @param oo 对角数据
     * @param zero 零的填充数据
     * @return 以oo为元素的对角矩阵
     */
    @SuppressWarnings("unchecked")
    public static <T> DataMatrix<T> diag( final T[] oo, final T zero){
        final Class<T> clazz = Arrays.stream(oo).filter(e->e!=null)
            .map(e->(Class<T>)e.getClass()).findAny().get();
        final var size = oo.length;
        Function<Integer,IRecord> line = i->{
            T[] tt = RPTA(size,zero);
            tt[i]= TypeU.coerce(oo[i],clazz);
            return A2REC(tt);
        };
        
        return Stream.iterate(0,i->i<size,i->i+1).map(line).collect(tmc(clazz));
    }
    
    /** 对角矩阵
    * @param <T> 元素类型
    * @param oo 对角数据
    * @return 以oo为元素的对角矩阵
    */
   @SuppressWarnings("unchecked")
   public static <T> DataMatrix<T> diag(final T[] oo){
       T zero = null;
       if(oo[0] instanceof Double) zero = (T)(Object)0d;
       else if(oo[0] instanceof Integer) zero = (T)(Object)0;
       else if(oo[0] instanceof Long) zero = (T)(Object) 0L;
       else if(oo[0] instanceof Float) zero = (T)(Object)0f;
       else if(oo[0] instanceof String) zero = (T)(Object)"";
       return diag(oo,zero);
   }
    
    /**
     * 对角矩阵
     * @param <T> 元素类型
     * @param n 矩阵尺寸
     * @param t 对角数据元素
     * @param zero 0值元素
     * @return 以oo为元素的对角矩阵
     */
    public static <T> DataMatrix<T> diag( final int n, final T t, final T zero){
        return diag(RPTA(n,t),zero);
    }
    
    /**
     * 对角矩阵
     * @param <T> 元素类型
     * @param n 方阵的行数 与 列数 即维度大小 
     * @param t 对角数据
     * @return 以oo为元素的对角矩阵
     */
    public static <T> DataMatrix<T> diag( final int n, final T t){
        @SuppressWarnings("unchecked")
        final T zero = P(0).toTarget(t!=null?(Class<T>)t.getClass():(Class<T>)Object.class);
        return diag(RPTA(n,t),zero);
    }
    
    /**
     * 对角矩阵:矩阵的元素的类型根据根据 n 的类型给与确认
     * @param <T> 元素类型
     * @param n 方阵的行数 与 列数 即维度大小
     * @return 以oo为元素的对角矩阵
     */
    @SuppressWarnings("unchecked")
    public static <T extends Number> DataMatrix<T> diag( final T n){
        final T one = P(1).toTarget(n!=null?(Class<T>)n.getClass():(Class<T>)(Object)Object.class);
        final T zero = P(0).toTarget(n!=null?(Class<T>)n.getClass():(Class<T>)(Object)Object.class);
        return diag(RPTA(n.intValue(),one),zero);
    }
    
    /**
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return 归集成object矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> omc(List<String> headers){
        return objmxclc(null,headers);
    }
    
    /**
     * 归集成Double矩阵的归集器
     * 
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return 归集成Double矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Double>> dmc(List<String> headers){
        return dblmxclc(record_identity(Double.class),headers);
    }
    
    /**
     * 归集成Integer矩阵的归集器
     * 
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return 归集成Integer矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Integer>> imc(List<String> headers){
        return intmxclc(record_identity(Integer.class),headers);
    }
    
    /**
     * 归集成 Long矩阵的归集器
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return 归集成Long矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Long>> lmc(List<String> headers){
        return lngmxclc(record_identity(Long.class),headers);
    }
    
    /**
     * 归集成 Long矩阵的归集器
     * @param headers 设置的matrix表头 null只表示不予设置 , 长度为0的LIST表示使用默认的 表头符号： EXCEL格式的名称 前面电邮一个  下划线的“_”, 例如:"_A","_B",...
     * @return 归集成String矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<String>> smc(List<String> headers){
        return strmxclc(record_identity(String.class),headers);
    }

    /**
     * 归集成 Object矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Object>> omc=OMC();
    
    /**
     * 归集成 Double矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Double>> dmc=DMC(record_identity(Double.class));
    
    /**
     * 归集成 Integer矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Integer>> imc=IMC(record_identity(Integer.class));
    
    /**
     * 归集成 Long矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<Long>> lmc=LMC(record_identity(String.class));
    
    /**
     * 归集成 String矩阵的归集器
     */
    public static Collector<IRecord, List<IRecord>, DataMatrix<String>> smc=SMC(record_identity(String.class));
    
    /**
     * 提取T结构的矩阵
     * @param <T> 目标元素类型
     * @param tclass 元素类型
     * @return 任意类型的搜集器
     */
    public static <T> Collector<IRecord, List<IRecord>, DataMatrix<T>> tmc(final Class<T>tclass){
        return TMC(record_identity(tclass),tclass);
    }

    /**
     * 带有类型的Record转换
     * @param <T> 目标元素类型
     * @param tclass 目标元素类型的class
     * @return 目标元素类型
     */
    public static <T> Function <IRecord,IRecord> record_identity(Class<T> tclass) {
        return (IRecord e)->{
            var t = e.apply(p->IRecord.rec2obj(REC(p),tclass));
            final var b = t.values().get(0)!=null;
            return b?t:e;
        };
    }
    
    /**
     * 常用的数学函数操作
     * @author gbench
     *
     */
    public static class MathOps {
        
        /**
         * 加法:之所以采用函数是为了使用泛型
         * @param <T> 元素类型
         * @return BinaryOperator
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number>  BinaryOperator<T> plus(){
            return (T a,T b) ->(T)(Number)(a.doubleValue()+b.doubleValue());
        }

        /**
         * 加法运算：例如，为一个序列中的每个元素加上10
         * Stream.of(1,2,3,4,5).map(multilier(10)).collect(Collectors.toList()) 产生:11.0, 12.0, 13.0, 14.0, 15.0
         * @param num 乘数
         * @return 乘数算子
         */
        public static Function<Number,Double> plus(Number num) {
            return (d)->d.doubleValue()+num.doubleValue();
        }

        /**
         * 序列中的每个值都增加num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] plus(final Number[]aa,Number num) {
           return Stream.of(aa).map(plus(num)).toArray(Double[]::new);
        }
        
        /**
         * 序列aa,序列bb的对应项的和
         * @param aa 数值序列
         * @param bb 数值序列
         * @return 结果序列
         */
        public static Double[] plus(final Number[]aa,Number []bb) {
           return Tuple2.zip2tups(aa, bb).map(p->p.map(plus())).toArray(Double[]::new);
        }

        /**
         * 序列中的每个值都增加num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] plus(final Collection<Number> aa,Number num) {
           return aa.stream().map(plus(num)).toArray(Double[]::new);
        }

        /**
         * 减法：之所以采用函数是为了使用泛型
         * @param <T> 元素类型
         * @return BinaryOperator
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number>  BinaryOperator<T> sub(){
            return (T a,T b) ->(T)(Number)(a.doubleValue()-b.doubleValue());
        }
        
        /**
         * 序列中的每个值都减去num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] sub(final Number[]aa,Number num) {
           return Stream.of(aa).map(sub(num)).toArray(Double[]::new);
        }

        /**
         * 序列aa,序列bb的对应项差
         * @param aa 数值序列
         * @param bb 数值序列
         * @return 结果序列
         */
        public static Double[] sub(final Number[]aa,Number []bb) {
           return Tuple2.zip2tups(aa, bb).map(p->p.map(sub())).toArray(Double[]::new);
        }
    
        /**
         * 序列中的每个值都减去num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] sub(final Collection<Number> aa,Number num) {
           return aa.stream().map(sub(num)).toArray(Double[]::new);
        }

        /**
         * 减法运算：例如，为一个序列中的每个元素减去10
         * Stream.of(1,2,3,4,5).map(substractor(10)).collect(Collectors.toList()) 产生:[-9.0, -8.0, -7.0, -6.0, -5.0]
         * @param num 乘数
         * @return 乘数算子
         */
        public static Function<Number,Double> sub (Number num) {
            return (d)->d.doubleValue()-num.doubleValue();
        }

        /**
         * 乘法：之所以采用函数是为了使用泛型
         * @param <T> 元素类型
         * @return 乘法
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number>  BinaryOperator<T> mul(){
            return (T a,T b) ->(T)(Number)(a.doubleValue()*b.doubleValue());
        }

        /**
         * 乘数运算：例如，为一个序列中的每个元素乘以10
         * Stream.of(1,2,3,4,5).map(multiplier(10)).collect(Collectors.toList()) 产生:[10.0, 20.0, 30.0, 40.0, 50.0]
         * @param num 乘数
         * @return 乘数算子
         */
        public static Function<Number,Double> mul(Number num) {
            return (d)->d.doubleValue()*num.doubleValue();
        }

        /**
         * 序列中的每个值都乘以num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] mul(final Number[]aa,Number num) {
           return Stream.of(aa).map(mul(num)).toArray(Double[]::new);
        }
        
        /**
         * 序列aa,序列bb的对应项乘积
         * @param aa 数值序列
         * @param bb 数值序列
         * @return 结果序列
         */
        public static Double[] mul(final Number[]aa,Number []bb) {
           return Tuple2.zip2tups(aa, bb).map(p->p.map(mul())).toArray(Double[]::new);
        }

        /**
         * 序列中的每个值都乘以num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] mul(final Collection<Number> aa,Number num) {
           return aa.stream().map(mul(num)).toArray(Double[]::new);
        }

        /**
         * 除法：之所以采用函数是为了使用泛型
         * @param <T> 元素类型
         * @return 除法
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number>  BinaryOperator<T> div(){
            return (T a,T b) ->(T)(Number)(a.doubleValue()/b.doubleValue());
        }

        /**
         * 序列中的每个值都除以num: 即 aa/num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] div(final Number[]aa,Number num) {
           return Stream.of(aa).map(div(num)).toArray(Double[]::new);
        }
        
        /**
         * aa/bb
         * @param aa 数值序列
         * @param bb 数值序列
         * @return 结果序列
         */
        public static Double[] div(final Number[]aa,Number []bb) {
           return Tuple2.zip2tups(aa, bb).map(p->p.map(div())).toArray(Double[]::new);
        }
        
        /**
         * bb/aa
         * @param aa 数值序列
         * @param bb 数值序列
         * @return 结果序列
         */
        public static Double[] div2(final Number[]aa,Number []bb) {
           return Tuple2.zip2tups(aa, bb).map(p->p.swap().map(div())).toArray(Double[]::new);
        }

        /**
         * b/aa
         * @param aa 数值序列
         * @param b 数值序列
         * @return 结果序列
         */
        public static Double[] div2(final Number[]aa,Number b) {
           return Tuple2.zip2tups(aa, new Number[] {b}).map(p->p.swap().map(div())).toArray(Double[]::new);
        }

        /**
         * 除法运算：例如，为一个序列中的每个元素除以10
         * Stream.of(1,2,3,4,5).map(divisor(10)).collect(Collectors.toList()) 产生:[0.1, 0.2, 0.3, 0.4, 0.5]
         * @param num 除数
         * @return 除数算子
         */
        public static Function<Number,Double> div(Number num) {
            return (d)->d.doubleValue()/num.doubleValue();
        }

        /**
         * 序列中的每个值都除以num
         * @param aa 数值序列
         * @param num 被加数
         * @return 结果序列
         */
        public static Double[] div(final Collection<Number> aa,Number num) {
           return aa.stream().map(div(num)).toArray(Double[]::new);
        }

        /**
         * 求两个数组 aa和bb的内积结果。积即 点积运算。
         * @param aa 数组1
         * @param bb 数组2
         * @return 内积结果
         */
        public static Double dot(final Number []aa,final Number []bb) {
            var a = Stream.of(aa).map(d->d.doubleValue()).collect(Collectors.toList());
            var b = Stream.of(bb).map(d->d.doubleValue()).collect(Collectors.toList());
            return KVPair.zip2tups(a,b).map(e->e._1()*e._2()).reduce((x,y)->x+y).orElse(null);
        }

        /**
         * 求两个数组 aa和bb的内积结果。积即 点积运算。
         * @param aa 数组1
         * @param bb 数组2
         * @return 内积结果
         */
        public static Double dot(final Collection<Number> aa,final Collection<Number> bb) {
        
            var a = aa.stream().map(d->d.doubleValue()).collect(Collectors.toList());
            var b = bb.stream().map(d->d.doubleValue()).collect(Collectors.toList());
            return KVPair.zip2tups(a,b).map(e->e._1()*e._2()).reduce((x,y)->x+y).orElse(null);
        }
        
        /**
         * 向量 alpha 在向量beta上的投影向量 
         * @param alpha 向量 alpha
         * @param beta 向量 beta
         * @return 投影向量
         */
        public static Number[] proj(Number[] alpha,Number[] beta) {
            return mul(beta,dot(alpha,beta)/dot(beta,beta));
        }
        
        /**
         * 对向量进行schmidt正交化：比较精度eps
         * @param alphas 源数据矩阵
         * @return 斯密特正交化的向量集合
         */
        public static List<Number[]> schmidt(final List<Number[]>alphas){
            final var eps = 1e-10;// 比较精度
            final var betas = new LinkedList<Number[]>();// 正交向量组。
            final Predicate<Number[]> is_not_zero = e->!Stream.of(e)
                .allMatch(n->Math.abs(n.doubleValue())<eps);// 是否为非零向量
            alphas.forEach(alpha->{
                final var p = betas.stream()
                    .map( beta -> proj(alpha,beta) )// 投影
                    .reduce(MathOps::plus)// 累加和
                    .map(v->(Number[])sub(alpha,v))// v 是alpha在各个分量（已经正交化分量）上的投影
                    .orElse(alpha);// 提取元素;当第alphas的第一个元素执行的时候,betas 为空.则直接返回alpha
                if(is_not_zero.test(p))betas.add(p);// 仅添加非0项链
            });// forEach
            
            return betas.stream().filter(e->e!=null).collect(Collectors.toList());
        }
        
        /**
         * 源向量集合
         * @param alphas 源数据矩阵
         * @return 斯密特正交化的向量集合
         */
        public static List<Number[]> schmidt(Number[][] alphas){
            var cc = DataMatrix.transpose(alphas);
            return schmidt(Arrays.asList(cc));
        }
        
        /**
         * 源向量集合
         * @param dmx 源数据矩阵
         * @return 斯密特正交化的向量集合
         */
        public static List<Number[]> schmidt(final DataMatrix<Double>dmx){
            return schmidt(dmx.getCells());
        }

        /**
         * 源向量集合
         * @param dmx 源数据矩阵
         * @return 斯密特正交化的向量集合
         */
        public static List<Number[]> schmidt_unitize(final DataMatrix<Double>dmx){
            return schmidt(dmx).stream()
                .map(MathOps::unitize)// 向量正交化
                .collect(Collectors.toList());
        }

        /**
         * 源向量集合:返回一个向量矩阵
         * @param dmx 源数据矩阵
         * @return 斯密特正交化的向量集合
         */
        public static DataMatrix<Double> schmidt_unitize2(final DataMatrix<Double>dmx){
            final var columns = schmidt(dmx).stream()
                .map(MathOps::unitize)// 向量正交化
                .collect(Collectors.toList());
            return DataMatrix.of3(columns).corece(Double.class);
        }

        /**
         *  把一个向量alpha 给与单位化(unitize)
         * @param alpha 向量
         * @return 单位化后的向量
         */
        public static Number[] unitize(final Number[] alpha) {
            return div(alpha,Math.sqrt(dot(alpha,alpha)));
        }

        /**
         * 阶乘函数
         * @param n 整数:
         * @return 阶乘结果
         */
        public static Long fact(Number n) {
            return n.longValue()== 0L ?1:n.longValue()*fact(n.longValue()- 1L);
        }

        /**
         * 生成一个随机方阵:  Square Random Matrix sqrm
         * @param <T> 方阵元素类型。
         * @param size 方阵尺寸
         * @return 随机方阵
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number> DataMatrix<T> sqrm(T size) {
            var dd = DBLS(size.intValue()*size.intValue());
            final Class<T> cls = (Class<T>)size.getClass();
            final var mm = SQB2(cls,size).get(Arrays.stream(dd)
                .toArray(n->(T[])Array.newInstance(cls,n)));// 随机生成一个矩阵
            return (DataMatrix<T>)mm;
        }
        
        /**
         * m * n 的全零矩阵, zero matrix
         * @param <T> 矩阵中的元素的类型
         * @param m 行数
         * @param n 列数
         * @return 全0的矩阵
         */
        @SuppressWarnings("unchecked")
        public static <T extends Number> DataMatrix<T> zerom(T m,T n) {
            final Class<T> cls = (Class<T>)m.getClass();
            final var mm = DMB2(cls,m,n).get(RPTS(m.intValue()*n.intValue(),m)
                .toArray(length->(T[])Array.newInstance(cls,length)));// 随机生成一个矩阵
            return (DataMatrix<T>)(mm.minus(mm));
        }
        
    }

    /**
     * 生成一个矩阵构造器
     * @author gbench
     *
     * @param <T> 矩阵元素类型
     */
    public static class DataMatrixBuilder<T>{
        
        /**
         * 矩阵构造器
         * @param typeClass 元素类型
         * @param m 行数高度
         * @param n 列数宽度
         */
        public DataMatrixBuilder( final Class<T>typeClass,final int m,final int n,Boolean byRow) {
            this.height = m;
            this.width = n;
            this.typeClass = typeClass;
            this.byRow = byRow;
        }
        
        /**
         * 矩阵构造器
         * @param typeClass 元素类型
         * @param m 行数高度
         * @param n 列数宽度
         */
        public DataMatrixBuilder( final Class<T>typeClass,final int m,final int n) {
            this.height = m;
            this.width = n;
            this.typeClass = typeClass;
            this.byRow = true;
        }
        
        /**
         * 矩阵构造器
         * @param m 行数高度
         * @param n 列数宽度
         */
        public DataMatrixBuilder(final int m,final int n) {
            this.height = m;
            this.width = n;
            this.typeClass = null;
            this.byRow =true;
        }
        
        /**
         * 创建矩阵
         * @param dd 矩阵数据元素:digits,doubles
         * @return DataMatrix &lt; T &gt;
         */
        public DataMatrix<Double> dblM(final double ...dd){
            return DataMatrixBuilder.get(Double.class, height, width, byRow,
                Arrays.stream(dd).boxed().toArray(Double[]::new));
        }
        
        /**
         * 创建矩阵
         * @param dd 矩阵数据元素:digits
         * @return DataMatrix &lt; T &gt;
         */
        public DataMatrix<Integer> intM(final int ...dd){
            return DataMatrixBuilder.get(Integer.class, height, width, byRow,
                    Arrays.stream(dd).boxed().toArray(Integer[]::new));
        }
        
        /**
         * 创建矩阵
         * @param dd 矩阵数据元素:digits
         * @return DataMatrix &lt; T &gt;
         */
        public DataMatrix<Long> lngM(final long ...dd){
            return DataMatrixBuilder.get(Long.class, height, width, byRow,
                    Arrays.stream(dd).boxed().toArray(Long[]::new));
        }

        /**
         * 创建矩阵
         * @param typeClass  元素类型类
         * @param height 矩阵高度（行数量）
         * @param width 矩阵宽度（列数量）
         * @param byRow 是否按照行顺序
         * @param oo 数据元素
         * @param <U> 矩阵的的类型
         * @return DataMatrix &lt; T &gt;
         */
        @SafeVarargs
        public static <U>DataMatrix<U> get(final Class<U> typeClass,int height,int width ,boolean byRow,final U ...oo){
            final int size =oo.length;
            @SuppressWarnings("unchecked")
            U[][] dd = DataMatrix.newArray(typeClass==null
                ? Stream.of(oo).filter(Objects::nonNull).findAny()
                        .map(e->(Class<U>)e.getClass()).orElse((Class<U>)Object.class)
                :typeClass,height,width);
            for(int i=0;i<height;i++) { // 列
                for(int j=0;j<width;j++) { // 列
                    int k = byRow // 参照是否按照行排序
                        ? (i*width+j)%size
                        : (j*height+i)%size;
                    dd[i][j]= oo[k]; // 元素设置
                }//j
            }//i
            
            return DataMatrix.of(dd,true);
        }
        
        /**
         * 创建矩阵
         * @param oo 矩阵数据元素
         * @return DataMatrix &lt; T &gt;
         */
        @SafeVarargs
        final public DataMatrix<T> get(final T ...oo){
           return DataMatrixBuilder.get(typeClass, height, width, byRow, oo);
        }
        
        /**
         * 创建数字矩阵:
         * @param nums 矩阵数据元素:numer 类型
         * @return DataMatrix &lt; T &gt;
         */
        public DataMatrix<Double> numerics(final Number ...nums){
           return DataMatrixBuilder.get(Double.class, height, width, byRow, 
                Stream.of(nums).map(Number::doubleValue).toArray(Double[]::new));
        }

        public Class<T> getTypeClass() {
            return typeClass;
        }

        public Boolean getByRow() {
            return byRow;
        }


        public int getHeight() {
            return height;
        }

        public int getWidth() {
            return width;
        }
        
        final private int height;
        final private int width;
        final private Class<T> typeClass;
        final private Boolean byRow;
    }
    
    /**
     * 生成一个按照行顺序的矩阵
     * @param <T>  元素类型
     * @param typeClass 元素类型
     * @param m 行数高度
     * @param n 列数宽度
     * @return DataMatrixBuilder<T>
     */
    public static <T> DataMatrixBuilder<T> DMB( final Class<T>typeClass,final Number m,final Number n){
       return new DataMatrixBuilder<T>(typeClass,m.intValue(),n.intValue());
    }
    
    /**
     * 生成一个按照列顺序的矩阵
     * @param <T> 元素类型
     * @param typeClass 元素类型
     * @param m 行数高度
     * @param n 列数宽度
     * @return DataMatrixBuilder<T>
     */
    public static <T> DataMatrixBuilder<T> DMB2( final Class<T>typeClass,final Number m,final Number n){
       return new DataMatrixBuilder<T>(typeClass,m.intValue(),n.intValue(),false);
    }

    /**
     * 生成一个按照行顺序的方阵:SQuareBuilder
     * @param <T>  元素类型
     * @param typeClass 元素类型
     * @param n 方阵维数
     * @return DataMatrixBuilder<T>
     */
    public static <T> DataMatrixBuilder<T> SQB( final Class<T>typeClass,final Number n){
       return new DataMatrixBuilder<T>(typeClass,n.intValue(),n.intValue());
    }
    
    /**
     * 生成一个按照列顺序的矩阵:SQuareBuilder
     * @param <T> 元素类型
     * @param typeClass 元素类型
     * @param n n 方阵维数
     * @return DataMatrixBuilder<T>
     */
    public static <T> DataMatrixBuilder<T> SQB2( final Class<T>typeClass,final Number n){
       return new DataMatrixBuilder<T>(typeClass,n.intValue(),n.intValue(),false);
    }

    /**
     * 生成一个按照行顺序的矩阵:SQuareBuilder
     * @param n 方阵维数
     * @return DataMatrixBuilder<Double>
     */
    public static DataMatrixBuilder<Double> DSQB(final Number n){
       return new DataMatrixBuilder<>(Double.class,n.intValue(),n.intValue(),true);
    }
    
    /**
     * 生成一个按照列顺序的矩阵:SQuareBuilder
     * @param n 方阵维数
     * @return DataMatrixBuilder<T>
     */
    public static DataMatrixBuilder<Double> DSQB2(final Number n){
       return new DataMatrixBuilder<>(Double.class,n.intValue(),n.intValue(),false);
    }

    /**
     * 把一个Double 二维数组转换成 double二数组
     * @param aa 一维数组
     * @return double[]
     */
    public static double[][] DD2dds( final Double[][]aa) {
        return Stream.of(aa).map(bb->Arrays.stream(bb).mapToDouble(Double::doubleValue).toArray()).toArray(double[][]::new);
    }
    
    /**
     * 把一个 double 二维数组转换成一个Double数组
     * @param aa 一维数组
     * @return Double[]
     */
    public static Double[][] dd2DDs( final double[][]aa) {
        return Arrays.stream(aa).map(bb->Arrays.stream(bb).boxed().toArray(Double[]::new)).toArray(Double[][]::new);
    }

    /**
     * 把一个Double 数组转换成 double数组
     * @param aa 一维数组
     * @return double[]
     */
    public static double[] D2ds( final Double[]aa) {
        return Arrays.stream(aa).mapToDouble(e->e).toArray();
    }

    /**
     * 把一个 double 数组转换成一个Double数组
     * @param aa 一维数组
     * @return  Double[]
     */
    public static Double[] d2Ds( final double[]aa) {
        return Arrays.stream(aa).boxed().toArray(Double[]::new);
    }
    
    /**
     * 矩阵转置
     * @param <T> 矩阵元素类型
     * @param mx 待转置的矩阵
     * @return 转置后的矩阵
     */
    public static <T> DataMatrix<T> transpose( final DataMatrix<T> mx){
        if(mx==null)return null;
        return mx.transpose();
    }
    
    /**
     * 矩阵转置
     * @param <T> 矩阵元素类型
     * @param mm 数据转置后的矩阵
     * @return 转置后的矩阵
     */
    public static <T> T[][] transpose( T[][] mm){
        if(mm==null)return null;
        return DataMatrix.transpose(mm);
    }
    
    /**
     * 矩阵转置
     * @param <T> 矩阵元素类型
     * @param mx 待转置的矩阵
     * @return 转置后的矩阵
     */
    public static <T> DataMatrix<T> t( final DataMatrix<T> mx){
        return transpose(mx);
    }
    
    /**
     * 快速生成一个元素为T类型的列表
     * @param <T> 列表元素类型
     * @param tt 列表元素序列
     * @return 列表
     */
    @SafeVarargs
    public static <T> List<T> l(final T ...tt) {
        return L(tt);
    }
    
    /**
     * 快速生成一个元素为T类型的列表
     * @param <T> 列表元素类型
     * @param filter 列表元素过滤器，当且仅当filter返回为true的元的元素才给与进行列表输出。
     * @param tt 列表元素序列
     * @return 列表
     */
    @SafeVarargs
    public static <T> List<T> l( final Predicate<T> filter,final T ...tt) {
        return Arrays.stream(tt).filter(e->filter.test(e)).collect(Collectors.toList());
    }
    
    /**
     * 快速生成一个T类型的元素流(STream st)
     * @param <T> 列表元素类型
     * @param filter 列表元素过滤器，当且仅当filter返回为true的元的元素才给与进行列表输出。
     * @param tt 列表元素序列
     * @return 采用filter 过滤后的流
     */
    @SafeVarargs
    public static <T> Stream<T> st( final Predicate<T> filter,final T ...tt) {
        return Arrays.stream(tt).filter(filter);
    }
    
    /**
     * 快速生成一个T类型的元素流 (STream st)
     * @param <T> 列表元素类型
     * @param tt 列表元素序列
     * @return tt构成的流
     */
    @SafeVarargs
    public static <T> Stream<T> st(final T ...tt) {
        return Arrays.stream(tt).filter(e->true);
    }
    
    /**
     * 快速生成一个T类型的数组
     * @param <T> 数组元素类型
     * @param tt 数组元素序列
     * @return 数组
     */
    @SafeVarargs
    @SuppressWarnings("unchecked")
    public static <T> T[] a(final T ...tt) {
        final Class<T> tclass = Stream.of(tt).filter(Objects::nonNull)
            .map(e->(Class<T>)e.getClass()).findFirst().get();
        return l(tt).toArray(n->(T[])Array.newInstance(tclass , n));
    }
    
    /**
     * 生成数据记录:IRecord.rec 的别名，用于 在不引用IRecord 情况下使用IRecord的函数。
     * @param ooo key0,value0, key1,value1, key2,value2,....
     * @return 数据记录
     */
    public static IRecord rec(final Object ... ooo) {
        return REC(ooo);
    }

    /**
     * 输出函数的会回调函数
     * @param lines 输出的数据内容
     * @param b 是否显示换行符号
     */
    protected BiConsumer<Boolean,Object[]> print_callback = (b,lines) -> {
        if(lines==null||lines.length<1) {
            if(b)System.out.println();
            return;
        }
        if(b)System.out.println(lines[0]);else System.out.print(Arrays.deepToString(lines));
    };

    /**
     * 行输出:System.out.println 的简写:只显示一行数据
     * @param lines 行对象
     * @return lines
     */
    public Object println( final Object ...lines) {
        print_callback.accept(true,lines);// 显示换行符号
        return lines;
    }
    
    /**
     * 行输出:System.out.println 的简写:只显示一行数据
     * @param lines 行对象
     * @return lines
     */
    public Object print( final Object ...lines) {
        print_callback.accept(false,lines);// 不显示换行符号
        return lines;
    }
    
    /**
     * 一元函数的别名
     * @author gbench
     *
     */
    public interface Fx extends Function<Object,Object>{} // 一元函数
    
    /**
     *  二元函数的别名
     * @author gbench
     *
     */
    public interface Fxy extends BiFunction<Object,Object,Object>{} // 二元函数
    
    /**
     * 把一个函数转换成Fx类型
     */
    public static Function<Function<Object,Object>,Fx> f2fx = (f)->(Fx) f::apply;
    /**
     * 把一个函数转换成Fxy类型
     */
    public static Function<BiFunction<Object,Object,Object>,Fxy> f2fxy = (f)->(Fxy) f::apply;
    
    /**
     *  函数复合:t->u->v
     * @param <T> g 的定义域类型
     * @param <U> g 的值域类型,f 的定义域类型
     * @param <V> f 的值域类型
     * @param g 被复合函数
     * @param f 复合函数
     * @return Fx T 为定义域 ，V为值域得新的函数
     */
    public static <T,U,V> Function<T,V> compose( final Function<T,U> g, final Function<U,V> f) {
        return f.compose(g);
    }
    
    /**
     * 函数流的序列复合：
     * [f1,f2,f3,...] -> f1(f2(f3(..))) 的复合函数。
     * @param ff 函数数列
     * @return Fx Object为定义域 Object为值域的函数
     */
    public static Fx ff2fx( final Stream<Function<Object,Object>> ff) {
        return ff.reduce(Function::compose).map(f2fx).get();
    }
    
    /**
     * 把一个 元素T类型的列表 tt  转换成一个 元素为U类型的列表 U uu
     * @param <T> 源数据元素类型
     * @param <U> 目的数据元素类型
     * @param mapper T 元素类型转换器 tt->uu
     * @return Collector 累加器 with:源元素类型 T,累加器类型   List &lt;U&gt; 结果类型 List&lt;U&gt;
     */
    public static <T,U> Collector<T,List<U>,List<U>>llclc( final Function<T,U>mapper){
        return objclc(mapper, e->e);
    }
    
    /**
     * 把一个元素为 T类型的列表 tt  转换成一个 元素为U类型的 数组U uu
     * @param <T> 源数据元素类型
     * @param <U> 目的数据元素类型
     * @param mapper T 元素类型转换器 tt->uu
     * @return Collector 累加器 with:源元素类型 T,累加器类型   List &lt;U&gt; 结果类型 List&lt;U&gt;
     */
    @SuppressWarnings("unchecked")
    public static <T,U> Collector<T,List<U>,U[]>aaclc( final Function<T,U>mapper){
        return objclc(mapper, uu->{
            final var componentType = uu.stream().filter(Objects::nonNull)
                .map(e->(Class<U>)e.getClass()).findAny().orElse((Class<U>)Object.class);
            return uu.stream().toArray(n->(U[])Array.newInstance(componentType,n));
        });
    }
    
    /**
     * 把一个元素为 T类型的列表 tt 通过mapper的中间变换累积成一个元素为类型的列表uu<br>
     * 并最终 通过finisher把这个元素为U类型的中间结果列表uu给转换成一个 O类型的目标对象(Objecive)。
     * 
     * @param <T> 源数据元素类型
     * @param <U> 中间数据元素类型
     * @param <O> 目的数据类型
     * @param mapper T 元素类型转换器 tt->uu 中间结果变换函数
     * @param finisher 把一个tt uu 列表转换成一个 O类型对象， 最终结果变换函数
     * @return 类型的对象
     */
    public static <T,U,O> Collector<T,List<U>,O>objclc(final Function<T,U>mapper,
        final Function<List<U>,O>finisher){
        
        return Collector.of(LinkedList::new
            , (aa,a)->aa.add(mapper.apply((T)a))
            , (aa,bb)->{aa.addAll(bb);return aa;}
            , finisher );
    }
    
    /**
     * 对函数矩阵应用乘法元素:<br>
     * product_operator T类型与U类型的向V类型进行映射的二元函数 (t,u)->v 使用 DataMatrixApp::compose  <br>
     * reducer V类型集合向O类型元素进行映射的多元函数 (...vvv)->o 使用 DataMatrixApp::ff2fx <br>
     * 
     * @param ltt 左边的函数矩阵
     * @param rtt 右边的函数矩阵
     * @return ltt 左乘 rtt 的新的函数矩阵。
     */
    public static DataMatrix<Fx> mmult2( final DataMatrix<Fx>ltt,DataMatrix<Fx>rtt){
        return ltt.mmult2(rtt,DataMatrixApp::compose,DataMatrixApp::ff2fx);
    }
    
    /**
     * 分解函数 <br>
     * 使用delimiters去分解 line,并把分解结果组成一个 字符串列表
     * @param line 待分解的字符串
     * @param delimiters 分隔符 默认为 "[,\\\\/]+" , delimiters 会 彼此依次串联成 一个模式字符串 交给  String.split(regex) 的 regex  用于 分解line。
     * @return 字符串列表
     */
    public static List<String> SPLIT(final String line,final String ...delimiters){
        final var regex = delimiters.length<1?"[,\\\\/]+": String.join("", delimiters);
        return Arrays.asList(line.split(regex));
    }
    
}
